package com.gitee.wsl.doc.prosemirror.ui.inputrule.ext

import com.gitee.wsl.doc.prosemirror.model.attr.Attrs
import com.gitee.wsl.doc.prosemirror.model.node.Node
import com.gitee.wsl.doc.prosemirror.model.node.NodeType
import com.gitee.wsl.doc.prosemirror.state.EditorState
import com.gitee.wsl.doc.prosemirror.state.Transaction
import com.gitee.wsl.doc.prosemirror.transform.ext.delete
import com.gitee.wsl.doc.prosemirror.transform.ext.setBlockType
import com.gitee.wsl.doc.prosemirror.ui.inputrule.InputRule
import com.gitee.wsl.doc.prosemirror.ui.inputrule.InputRuleHandler
import com.gitee.wsl.doc.prosemirror.ui.inputrule.toInputRule

class TextblockTypeInputRuleHandler<T : Node>(
    private val nodeType: NodeType,
    private val getAttrs: ((MatchResult?) -> Attrs?)? = null
): InputRuleHandler {

    /**
     * 执行输入规则处理
     * @param state 编辑器状态
     * @param match 正则匹配结果
     * @param start 匹配开始位置
     * @param end 匹配结束位置
     * @return 处理事务，如果不适用则返回null
     */
    override fun execute(
        state: EditorState,
        match: MatchResult,
        start: Int,
        end: Int
    ): Transaction? {
        val startPos = state.doc.resolve(start)

        // 获取节点属性
        val attrs = getAttrs?.invoke(match)

        // 检查父节点是否允许替换为指定节点类型
        val parent = startPos.node(-1)
        if (!parent.canReplaceWith(
                startPos.index(-1),
                startPos.indexAfter(-1),
                nodeType
            )) {
            return null
        }

        // 创建事务：删除匹配文本并设置新的块类型
        return state.tr
            .delete(start, end)
            .setBlockType(start, start, nodeType, attrs)
    }

    companion object {
        /**
         * 创建文本块类型输入规则
         * @param regexp 匹配正则表达式（通常以^开头）
         * @param nodeType 目标节点类型
         * @param getAttrs 属性获取函数或静态属性（可为null）
         */
        fun <T : Node> create(
            nodeType: NodeType,
            getAttrs:((MatchResult?) -> Attrs)? = null
        ): TextblockTypeInputRuleHandler<T> {
            return TextblockTypeInputRuleHandler( nodeType, getAttrs)
        }

        fun <T : Node> create(
            nodeType: NodeType,
            attrs: Attrs? = null
        ): TextblockTypeInputRuleHandler<T> {
            return TextblockTypeInputRuleHandler(nodeType) { attrs }
        }
    }
}

fun<T : Node> InputRule.Companion.textblockType(
                                      regex: Regex,
                                      nodeType: NodeType,
                                      getAttrs:((MatchResult?) -> Attrs)? = null,
                                      options: InputRule.Options = InputRule.Options()
) = TextblockTypeInputRuleHandler.create<T>(nodeType,getAttrs).toInputRule(regex,options)
